package com.lxy.controller;

import com.lxy.es.bean.Product;
import com.lxy.req.SearchPageReq;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.MatchQueryBuilder;
import org.elasticsearch.index.query.Operator;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.RangeQueryBuilder;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.ScoreSortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.IndexOperations;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author lixueyang
 * @since 2022/4/20 17:43
 */
@RestController
@RequestMapping("/es")
public class EsOptController {

    @Resource
    ElasticsearchRestTemplate elasticsearchRestTemplate;

    /**
     * 删除索引
     *
     * @param name
     * @return
     */
    @GetMapping("/delIndex/{name}")
    public String delIndex(@PathVariable String name) {
        IndexCoordinates idx = IndexCoordinates.of(name);
        IndexOperations idxOps = elasticsearchRestTemplate.indexOps(idx);
        idxOps.delete();

        return "success";
    }


    @GetMapping("/multiGet")
    public List<Product> searchPage(SearchPageReq req) {

        Pageable pageable = PageRequest.of(req.getPageNo(), req.getPageSize());

        BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();

        if (StringUtils.isNotEmpty(req.getName())) {
            //设置字段属性为keyword, matchQuery就不会进行分词，不设置是，matchQuery会将入参进行分词处理进行搜索
            boolQueryBuilder.must(QueryBuilders.matchQuery("name.keyword", req.getName()));
        }

        if (StringUtils.isNotEmpty(req.getContent())) {
            //分词搜索匹配，设置了Operator.AND和75%意思是当字段包含分词的75%及以上才能符合结果
            boolQueryBuilder.must(QueryBuilders.matchQuery("content", req.getContent())
                    .operator(Operator.AND)
                    .minimumShouldMatch("75%"));
        }

        if (StringUtils.isNotEmpty(req.getSearchKey())) {
            //从几个字段里面同时检索
            boolQueryBuilder.should(QueryBuilders.multiMatchQuery(req.getSearchKey(), "name", "width"));
        }

        if (Objects.nonNull(req.getMinWidth()) || Objects.nonNull(req.getMaxWidth())) {
            RangeQueryBuilder widthRange = QueryBuilders.rangeQuery("width");
            if (Objects.nonNull(req.getMinWidth())) {
                widthRange.gte(req.getMinWidth());
            }

            if (Objects.nonNull(req.getMaxWidth())) {
                widthRange.lte(req.getMaxWidth());
            }

            boolQueryBuilder.filter(widthRange);
        }

        if (Objects.nonNull(req.getMinHeight()) || Objects.nonNull(req.getMaxHeight())) {
            RangeQueryBuilder heightRange = QueryBuilders.rangeQuery("height");
            if (Objects.nonNull(req.getMinHeight())) {
                heightRange.gte(req.getMinHeight());
            }

            if (Objects.nonNull(req.getMaxHeight())) {
                heightRange.lte(req.getMaxHeight());
            }

            boolQueryBuilder.filter(heightRange);
        }

        if (Objects.nonNull(req.getPubStatus())) {
            boolQueryBuilder.filter(QueryBuilders.termQuery("pubStatus", req.getPubStatus()));
        }

        //相关性排序
        ScoreSortBuilder scoreSort = SortBuilders.scoreSort().order(SortOrder.DESC);
        //排序
        FieldSortBuilder widthSort = SortBuilders.fieldSort("width").order(SortOrder.DESC);

        NativeSearchQuery query = new NativeSearchQueryBuilder()
                .withQuery(boolQueryBuilder)
                .withPageable(pageable)
                .withSort(scoreSort).withSort(widthSort)
                .build();

        SearchHits<Product> search = elasticsearchRestTemplate.search(query, Product.class);

        List<Product> productList = new ArrayList<>();

        if (search.getTotalHits() > 0) {
            productList = search.getSearchHits().stream().map(SearchHit::getContent).collect(Collectors.toList());
        }

        return productList;
    }
}
